//
//  NSData+RCDES.m
//  StructToolsDemo
//
//  Created by 杨晓辉 on 2017/8/22.
//  Copyright © 2017年 杨晓辉. All rights reserved.
//

#import "NSData+RCDES.h"
#import <CommonCrypto/CommonCryptor.h>
#define gkey            @"01234567"
//#define IV             @"01234567"
@implementation NSData (RCDES)
/**
 DES 加密
 
 @param key 密钥
 @param offset 偏移量
 @param sourceData 待加密数据
 @return 加密后的密文
 */
+ (NSData *)encryptDESWithKey:(NSString*)key andOffset:(NSString*)offset andSourceData:(NSData*)sourceData
{
    size_t plainTextBufferSize = [sourceData length];
    const void *vplainText = (const void *)[sourceData bytes];
    
    CCCryptorStatus ccStatus;
    uint8_t *bufferPtr = NULL;
    size_t bufferPtrSize = 0;
    size_t movedBytes = 0;
    
    bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
    bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
    memset((void *)bufferPtr, 0x0, bufferPtrSize);
    
    const void *vkey = (const void *) [key UTF8String];
    const void *vinitVec = (const void *) [offset UTF8String];
    
    ccStatus = CCCrypt(kCCEncrypt,
                       kCCAlgorithmDES,
                       kCCOptionPKCS7Padding,
                       vkey,
                       kCCKeySizeDES,
                       vinitVec,
                       vplainText,
                       plainTextBufferSize,
                       (void *)bufferPtr,
                       bufferPtrSize,
                       &movedBytes);
    
    NSData  *encryptData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
    return encryptData;
}

/**
 DES 解密
 
 @param key 秘钥
 @param offset 偏移量
 @param sourceData 待解密的数据
 @return 解密后的数据
 */
+ (NSData *)decryptDESWithKey:(NSString*)key andOffset:(NSString*)offset andSourceData:(NSData*)sourceData
{
    size_t plainTextBufferSize = [sourceData length];
    const void *vplainText = [sourceData bytes];
    
    CCCryptorStatus ccStatus;
    uint8_t *bufferPtr = NULL;
    size_t bufferPtrSize = 0;
    size_t movedBytes = 0;
    
    bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
    bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
    memset((void *)bufferPtr, 0x0, bufferPtrSize);
    
    const void *vkey = (const void *) [key UTF8String];
    const void *vinitVec = (const void *) [offset UTF8String];
    
    ccStatus = CCCrypt(kCCDecrypt,
                       kCCAlgorithmDES,
                       kCCOptionPKCS7Padding,
                       vkey,
                       kCCKeySizeDES,
                       vinitVec,
                       vplainText,
                       plainTextBufferSize,
                       (void *)bufferPtr,
                       bufferPtrSize,
                       &movedBytes);
    NSData *decryptData = [NSData dataWithBytes:(const void *)bufferPtr
                                         length:(NSUInteger)movedBytes];
    return decryptData;
}
+ (NSData*)encrypt3DESWithKey:(NSString*)key andOffset:(NSString*)offset andSourceData:(NSData*)sourceData
{
    NSData* data = sourceData;
    size_t plainTextBufferSize = [data length];
    const void *vplainText = (const void *)[data bytes];
    
    CCCryptorStatus ccStatus;
    uint8_t *bufferPtr = NULL;
    size_t bufferPtrSize = 0;
    size_t movedBytes = 0;
    
    bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
    bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
    memset((void *)bufferPtr, 0x0, bufferPtrSize);
    //*****kCCAlgorithm3DES的长度是24 vkey也得24
    const void *vkey = (const void *) [[NSString stringWithFormat:@"%@%@%@",key,key,key] UTF8String];
    const void *vinitVec = (const void *) [offset UTF8String];
    
    ccStatus = CCCrypt(kCCEncrypt,
                       kCCAlgorithm3DES,
                       kCCOptionPKCS7Padding,
                       vkey,
                       kCCKeySize3DES,
                       vinitVec,
                       vplainText,
                       plainTextBufferSize,
                       (void *)bufferPtr,
                       bufferPtrSize,
                       &movedBytes);
    
    NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
    return myData;
}
/**
 3DES 解密
 
 @param key 密钥
 @param offset 偏移量
 @param sourceData 待解密数据
 @return 解密后的数据
 */
+ (NSData*)decrypt3DESWithKey:(NSString*)key andOffset:(NSString*)offset andSourceData:(NSData*)sourceData
{
    
    
    NSData *encryptData = sourceData;
    size_t plainTextBufferSize = [encryptData length];
    const void *vplainText = [encryptData bytes];
    
    CCCryptorStatus ccStatus;
    uint8_t *bufferPtr = NULL;
    size_t bufferPtrSize = 0;
    size_t movedBytes = 0;
    
    bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
    bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
    memset((void *)bufferPtr, 0x0, bufferPtrSize);
    
    //*****kCCAlgorithm3DES的长度是24 vkey也得24
    const void *vkey = (const void *) [[NSString stringWithFormat:@"%@%@%@",key,key,key] UTF8String];
    const void *vinitVec = (const void *) [offset UTF8String];
    
    ccStatus = CCCrypt(kCCDecrypt,
                       kCCAlgorithm3DES,
                       kCCOptionPKCS7Padding,
                       vkey,
                       kCCKeySize3DES,
                       vinitVec,
                       vplainText,
                       plainTextBufferSize,
                       (void *)bufferPtr,
                       bufferPtrSize,
                       &movedBytes);
    
    NSData *decryptData = [NSData dataWithBytes:(const void *)bufferPtr
                                         length:(NSUInteger)movedBytes];
    return decryptData;
}

@end
